home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 238 < prev    next >
Encoding:
Text File  |  1996-08-06  |  4.4 KB  |  147 lines

  1. Path: engnews1.Eng.Sun.COM!taumet!clamage
  2. From: James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>
  3. Newsgroups: comp.std.c++
  4. Subject: Re: Explicit constructor call vs Temporaries
  5. Date: 2 Feb 1996 15:49:12 GMT
  6. Organization: ?
  7. Approved: clamage@eng.sun.com (comp.std.c++)
  8. Message-ID: <9602021214.AA07865@lts.sel.alcatel.de>
  9. References: <4e6plv$idn@eclipse.eng.sc.rolm.com> <4eq5p2$fpu@fsuj01.rz.uni-jena.de>
  10. NNTP-Posting-Host: taumet.eng.sun.com
  11. Content-Type: text
  12. In-Reply-To: mkt@isun04.inf.uni-jena.de's message of 01 Feb 1996 09:54:08 PST
  13. Content-Length: 3667
  14. X-Lines: 125
  15. Originator: clamage@taumet
  16.  
  17. In article <4eq5p2$fpu@fsuj01.rz.uni-jena.de>
  18. mkt@isun04.inf.uni-jena.de (Tilo Koerbs) writes:
  19.  
  20. |>  About the error message in this posted code:
  21.  
  22. |> > class T {
  23. |> >   T();
  24. |> >   ~T();
  25. |> > }
  26. |> > 
  27. |> > class X {
  28. |> >   X();
  29. |> >   ~X();
  30. |> >   f(T& t);
  31. |> > }
  32. |> > 
  33. |> > int main() {
  34. |> >   X x;
  35. |> >   x.f(T());  // Compiler complained on this line
  36. |> > }
  37.  
  38. |> The 'temporary' (it is an UNNAMED) T()-object is NOT const!
  39. |> Consider:
  40. |>     class T {
  41. |>     public:
  42. |>         T();
  43. |>         ~T();
  44. |>         void nonConstFct() {}
  45. |>     };
  46.  
  47. |>     int main() {
  48. |>         T().nonConstFct();  // Allowed!!!
  49. |>     }
  50.  
  51. |> And so the compiler should have no problem with this code!
  52. |> I compiled it without any problem!
  53.  
  54. Except that the rules forbid binding a temporary to a non-const
  55. reference, independantly of whether the temporary is const or not.
  56. (See section 8.5.3 in the draft standard: "If the initializer
  57. expression is an lvalue ... Otherwise, the reference shall be to a
  58. non-volatile const type."
  59.  
  60. Both g++ 2.7.2 and Sun CC 3.0.1 (the old cfront version) issue
  61. warnings about this.  Curiously enough, Sun CC 4.0.1 doesn't, on this
  62. platform (Sun CC 4.1), although I seem to remember warnings from this
  63. compiler under Solaris.  The Sun warnings state "anachronism", and in
  64. fact, this rule was added to the language (at least five or six years
  65. ago), so some older compilers may not be aware of it.
  66.  
  67. The rule was introduced to avoid errors in cases like the following:
  68.  
  69.     void
  70.     incr( int& i )
  71.     {
  72.         i ++ ;
  73.     }
  74.  
  75.     void
  76.     user()
  77.     {
  78.         unsigned        x( 5 ) ;
  79.         incr( x ) ;
  80.     }
  81.  
  82. In the call to `incr', the compiler must convert x to an int; the
  83. result of such a conversion is a temporary.  Before the rule was
  84. adapted, the temporary was bound to the reference, and modified by the
  85. function `incr'.  This is generally *NOT* what the author of user
  86. wanted or expected (since `x' remains unchanged).  Note that this is
  87. not a problem with const references, since there is presumably no
  88. modification to get lost.
  89.  
  90. The solution I'm using (since yesterday, when I thought of it:-) is to
  91. add a function to T:
  92.  
  93.     T&
  94.     T::lvalue()
  95.     {
  96.         return *this ;
  97.     }
  98.  
  99. And in the main, above:
  100.  
  101.     int
  102.     main()
  103.     {
  104.         X               x ;
  105.         x.f( T().lvalue() ) ;
  106.         return 0 ;
  107.     }
  108.  
  109. As you point out, the temporary isn't const, so I can call a non-const
  110. function (like `lvalue') on it.  And a reference *is* an lvalue (by
  111. definition), so it can bind to a non-const reference.
  112.  
  113. This solution has the advantage (IMHO) of requiring the user to say,
  114. yes, I know that I'm going to modify a temporary, but that's what I
  115. want.  It also retains const-safety; as the function `lvalue' is not
  116. const, it cannot be called on a const object.
  117.  
  118. The major disadvantage is that it requires adding a function to T.
  119. For classes where one expects this type of behavior (e.g.: auto_ptr),
  120. one would probably add the function.  But the user who needs it
  121. exceptionally for a class where it is not the normal case is stuck.
  122. (I have a case where I need it from ostrstream!)  Of course, there is
  123. always derivation:
  124.  
  125.     class MyStrStream : public ostrstream
  126.     {
  127.     public :
  128.         ostrstream&         lvalue() { return *this ; }
  129.     } ;
  130.  
  131. I'm not sure, but I think that `static_cast< T& >( T() )' should also
  132. work.  (This is OK for the occasional exceptional usage, but for cases
  133. where I expect my user to normally use a temporary, I'll provide the
  134. derived class.)
  135.  
  136. --
  137. James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
  138. GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
  139. Conseils, Θtudes et rΘalisations en logiciel orientΘ objet --
  140.                 -- A la recherche d'une activitΘ dans une region francophone
  141.  
  142.  
  143. [ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  144.   Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy is
  145.   summarized in http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
  146. ]
  147.